package com.twu.biblioteca.App;

import com.twu.biblioteca.Models.*;

import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

public class BibliotecaApp {

    private User user;
    public  Library library;
    private Menu appMenu;
    private Scanner scanner;
    private boolean userHasLoggedIn;

    public BibliotecaApp() {
        //Instantiate variables
        instantiateLibrary();
        appMenu = new Menu();
        scanner = new Scanner(System.in);

        userHasLoggedIn = false;
    }

    public static void main(String[] args) {
        BibliotecaApp app = new BibliotecaApp();
        app.startApp();
    }

    public String processMenuOption(Menu.MenuOption option) {

        String messageToUser = "";

        if (option != null) {
            if (option.requiresLogInToExecute() && !userHasLoggedIn) {
                LogInDetails enteredDetails = captureLogInDetails();
                if (!logUserIn(enteredDetails)) {
                    System.out.println("Invalid Log In Details.");
                    captureLogInDetails();
                }
            }
        }
        else {
            return "Select a valid option!!";
        }

        switch (option.getId()) {
            case 0: {
                //Exit Application
                System.out.println("Closing Application...");
                System.exit(0);
            }
            case 1: {
                library.printListOfBooksInLibrary();
                break;
            }
            case 2: {
                System.out.println("Enter book ISBN...");
                String bookIsbn = scanner.nextLine();
                Book bookToReserve = library.getBook(bookIsbn);
                messageToUser = library.reserveBook(bookToReserve);
                break;
            }
            case 3: {
                if (userHasLoggedIn)
                    messageToUser = user.getMembershipDetails();
                else
                    messageToUser = "Please talk to a Librarian. Thank you.";
                break;
            }
            case 4: {
                library.printListOfMoviesInLibrary();
                break;
            }
            default: messageToUser = "Coming Soon...";
        }
        return messageToUser;
    }

    //Lets the app start listening for and processing input
    private void startApp() {
        appMenu.print();
        Scanner scanner = new Scanner(System.in);
        int selectedOptionId = scanner.nextInt();
        Menu.MenuOption menuOptionToExecute = appMenu.parseIntAsMenuOption(selectedOptionId);
        System.out.println(processMenuOption(menuOptionToExecute));
    }

    private LogInDetails captureLogInDetails(){
        System.out.println("Please Log in to access this feature.");
        System.out.println("Library Number:");
        String libraryNumber = scanner.nextLine().trim();
        int username = LogInDetails.parseStringAsUsername(libraryNumber);
        System.out.println("Password:");
        String password = scanner.nextLine().trim();
        return new LogInDetails(username, password);
    }

    @SuppressWarnings("deprecation")
    private  void instantiateLibrary() {
        library = new Library();

        //Add hard coded books for now.
        Book book1 = new Book("Mathematical Programming in Java", "ISBN000000001");
        library.addBook(book1);

        Book book2 = new Book("African Partying", "ISBN000000002");
        library.addBook(book2);

        Book book3= new Book("Ghandi - a Biography", "ISBN000000004");
        library.addBook(book3);

        //Add hard coded movies for now
        Movie movie1 = new Movie("Les Miserables", new Date(2012, 12, 15), "Tom Hooper");
        movie1.rate(8);
        library.addMovie(movie1);
        Movie movie2 = new Movie("Avatar", new Date(2009, 12, 10), "James Cameron");
        movie2.rate(9);
        library.addMovie(movie2);
        Movie movie3 = new Movie("Apocalypto", new Date(2006, 12, 8), "Mel Gibson");
        movie3.rate(10);
        library.addMovie(movie3);
        Movie movie4 = new Movie("Connectionaire", new Date(2007, 11, 23), "Jason Fridel");
        movie4.rate(7);
        library.addMovie(movie4);
        Movie movie5 = new Movie("Blown Down", new Date(2003, 1, 15), "Frank Gilbert");
        movie5.rate(2);
        library.addMovie(movie5);
        Movie movie6 = new Movie("The Man That Never Was", new Date(2012, 12, 15), "Jude Simpson");
        movie6.rate(9);
        library.addMovie(movie6);
        Movie movie7 = new Movie("Incredible", new Date(2013, 1, 5), "William Sawyer");
        library.addMovie(movie7);
        Movie movie8 = new Movie("Square One", new Date(1999, 12, 3), "Genero Thomson");
        movie8.rate(7);
        library.addMovie(movie8);
        Movie movie9 = new Movie("Renegade", new Date(1985, 7, 31), "Constantine Virginia");
        movie9.rate(1);
        library.addMovie(movie9);
        Movie movie10 = new Movie("Impromptu, Uninvited", new Date(2005, 9, 20), "Seth Nexon");
        movie10.rate(6);
        library.addMovie(movie10);
        Movie movie11 = new Movie("Blind Date", new Date(2010, 1, 19), "Jaqueline Katina");
        movie11.rate(6);
        library.addMovie(movie11);
        Movie movie12 = new Movie("Subtle", new Date(2010, 4, 16), "Natasha Brood");
        movie12.rate(5);
        library.addMovie(movie12);
        Movie movie13 = new Movie("Broken", new Date(2012, 10, 11), "George Thomas");
        movie13.rate(8);
        library.addMovie(movie13);
        Movie movie14 = new Movie("Black Snow", new Date(1998, 6, 5), "Michael Dell");
        movie14.rate(9);
        library.addMovie(movie14);
        Movie movie15 = new Movie("Glare", new Date(2007, 2, 25), "Orwell Reagan");
        movie15.rate(10);
        library.addMovie(movie15);

        //Add 2 new users, hard coded for now
        User pioneerUser = new User("Nimrod", "Wandera", "Makindye, Luwafu", makeNewLogInDetails());
        library.addUser(pioneerUser);
        User secondUser = new User("Jesse", "Wejuli", "Makindye, Salaama", makeNewLogInDetails());
        library.addUser(secondUser);

        System.out.println("\nHello! Welcome to Biblioteca.");
    }

    /**
     * Fetches the details of the last registered user in the library
     * and creates new sign-in details using an incremental model for
     * the username and random password generation.
     * @return a new password and username wrapped as a <code>LogInDetailss</code> object
     */
    public LogInDetails makeNewLogInDetails() {

        List<User> registeredUsers = library.getUsers();
        int lastRegisteredUserName = 1111110; //Default 1st username less 1

        if (!registeredUsers.isEmpty()) {
            User lastRegisteredUser = registeredUsers.get(registeredUsers.size() - 1);
            lastRegisteredUserName = lastRegisteredUser.getLogInDetails().getUsername();
        }

        //Generate only 3-digit random passwords
        String newPassword = "";
        for (int i = 0; i < 3; i++) {
            newPassword += new Random().nextInt(9);
        }

        LogInDetails newDetails = new LogInDetails(lastRegisteredUserName + 1, newPassword);

        //Print out details for test running purposes
        String libraryNumber = newDetails.getLibraryNumber();
        System.out.println("New User Details:\n" +  libraryNumber + ", " + newDetails.getPassword());

        return newDetails;
    }

    /**
     * @return True if the log in details were correct, false otherwise.
     */
    public boolean logUserIn(LogInDetails detailsToTest) {

        boolean logInDetailsExist = false;
        List<User> registeredUsers = library.getUsers();

        for (User user: registeredUsers) {
            LogInDetails userLogInDetails = user.getLogInDetails();
            if (userLogInDetails.getUsername() == detailsToTest.getUsername()
                    && userLogInDetails.getPassword().equals(detailsToTest.getPassword())) {
                logInDetailsExist = true;
                this.user = user;
                userHasLoggedIn = true;
                break;
            }
        }
        return  logInDetailsExist;
    }
}
